﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AAA.Meta.Quote;

namespace AAA.Meta.Chart.Data
{
    public class BarData
    {
        private List<DateTime> _lstDateTime;
        private List<float> _lstOpen;
        private List<float> _lstHigh;
        private List<float> _lstLow;
        private List<float> _lstClose;
        private List<float> _lstVolume;
        private BarCompressionEnum _eBarCompression;
        private float _fYMin;
        private float _fYMax;

        public BarData()
            : this(BarCompressionEnum.Daily)
        {
        }

        public BarData(BarCompressionEnum eBarCompression)
        {
            _eBarCompression = eBarCompression;
            _lstDateTime = new List<DateTime>();
            _lstOpen = new List<float>();
            _lstHigh = new List<float>();
            _lstLow = new List<float>();
            _lstClose = new List<float>();
            _lstVolume = new List<float>();
            _fYMax = float.MinValue;
            _fYMin = float.MaxValue;
        }

        public BarCompressionEnum BarCompression
        {
            get { return _eBarCompression; }
        }

        public int GetLength()
        {            
            return _lstDateTime.Count;
        }

        public DateTime DateTime()
        {
            return DateTime(_lstDateTime.Count - 1);
        }

        public DateTime DateTime(int iIndex)
        {
            if ((iIndex >= _lstDateTime.Count) || (iIndex < 0))
                return System.DateTime.MinValue;

            return _lstDateTime[iIndex];
        }

        public float Open()
        {
            return Open(_lstOpen.Count - 1);
        }

        public float Open(int iIndex)
        {
            if ((iIndex >= _lstOpen.Count) || (iIndex < 0))
                return float.NaN;

            return _lstOpen[iIndex];
        }

        public float High()
        {
            return High(_lstHigh.Count - 1);
        }

        public float High(int iIndex)
        {
            if ((iIndex >= _lstHigh.Count) || (iIndex < 0))
                return float.NaN;

            return _lstHigh[iIndex];
        }

        public float Low()
        {
            return Low(_lstLow.Count - 1);
        }

        public float Low(int iIndex)
        {
            if ((iIndex >= _lstLow.Count) || (iIndex < 0))
                return float.NaN;

            return _lstLow[iIndex];
        }

        public float Close()
        {
            return Close(_lstClose.Count - 1);
        }

        public float Close(int iIndex)
        {
            if (iIndex >= _lstClose.Count || iIndex < 0)
                return float.NaN;

            return _lstClose[iIndex];
        }

        public float Volume()
        {
            return Volume(_lstVolume.Count - 1);
        }

        public float Volume(int iIndex)
        {
            if (iIndex >= _lstVolume.Count || iIndex < 0)
                return float.NaN;

            return _lstVolume[iIndex];
        }

        public void AddTick(DateTime dtTime, float fClose, float fTickVolume)
        {
            DateTime dtBar = new DateTime(dtTime.Year, dtTime.Month, dtTime.Day, dtTime.Hour, dtTime.Minute, 0);
            dtBar.AddMinutes(1);
            int iDateTimeIndex = _lstDateTime.IndexOf(dtBar);

            if (iDateTimeIndex < 0)
            {
                _lstDateTime.Add(dtBar);
                _lstOpen.Add(fClose);
                _lstHigh.Add(fClose);
                _lstLow.Add(fClose);
                _lstClose.Add(fClose);
                _lstVolume.Add(fTickVolume);
            }
            else
            {
                _lstDateTime[iDateTimeIndex] = dtBar;                
                _lstHigh[iDateTimeIndex] = Math.Max(_lstHigh[iDateTimeIndex], fClose);
                _lstLow[iDateTimeIndex] = Math.Min(_lstLow[iDateTimeIndex], fClose);
                _lstClose[iDateTimeIndex] = fClose;
                _lstVolume[iDateTimeIndex] += fTickVolume;
            }

        }

        public void AddData(DateTime dtTime, float fOpen, float fHigh, float fLow, float fClose, float fVolume)
        {
            DateTime dtBar = new DateTime(dtTime.Year, dtTime.Month, dtTime.Day, dtTime.Hour, dtTime.Minute, 0);
            dtBar.AddMinutes(1);

            //int iDateTimeIndex = _lstDateTime.IndexOf(dtTime);
            int iDateTimeIndex = _lstDateTime.IndexOf(dtBar);

            if (iDateTimeIndex < 0)
            {
                _lstDateTime.Add(dtBar);
                _lstOpen.Add(fOpen);
                _lstHigh.Add(fHigh);
                _lstLow.Add(fLow);
                _lstClose.Add(fClose);
                _lstVolume.Add(fVolume);

/*
                _lstDateTime.Insert(0, dtTime);
                _lstOpen.Insert(0, fOpen);
                _lstHigh.Insert(0, fHigh);
                _lstLow.Insert(0, fLow);
                _lstClose.Insert(0, fClose);
                _lstVolume.Insert(0, fVolume);
*/ 
            }
            else
            {
                _lstDateTime[iDateTimeIndex] = dtBar;
                _lstOpen[iDateTimeIndex] = fOpen;
                _lstHigh[iDateTimeIndex] = fHigh;
                _lstLow[iDateTimeIndex] = fLow;
                _lstClose[iDateTimeIndex] = fClose;
                _lstVolume[iDateTimeIndex] = fVolume;
/*
                _lstDateTime.RemoveAt(iDateTimeIndex);
                _lstOpen.RemoveAt(iDateTimeIndex);
                _lstHigh.RemoveAt(iDateTimeIndex);
                _lstLow.RemoveAt(iDateTimeIndex);
                _lstClose.RemoveAt(iDateTimeIndex);
                _lstVolume.RemoveAt(iDateTimeIndex);

                _lstDateTime.Insert(iDateTimeIndex, dtTime);
                _lstOpen.Insert(iDateTimeIndex, fOpen);
                _lstHigh.Insert(iDateTimeIndex, fHigh);
                _lstLow.Insert(iDateTimeIndex, fLow);
                _lstClose.Insert(iDateTimeIndex, fClose);
                _lstVolume.Insert(iDateTimeIndex, fVolume);
 */ 
            }
        }

        public void UpdateLastData(float fPrice, float fVolume)
        {
            _lstClose[_lstClose.Count - 1] = fPrice;
            _lstVolume[_lstVolume.Count - 1] = fVolume;

            if (fPrice > _lstHigh[_lstHigh.Count - 1])
                 _lstHigh[_lstHigh.Count - 1] = fPrice;


            if (fPrice < _lstLow[_lstLow.Count - 1])
                _lstLow[_lstLow.Count - 1] = fPrice;
        }

        public float YMin
        {
            get { return _lstLow.Min(); }
        }

        public float YMax
        {
            get { return _lstHigh.Max(); }
        }

        public List<float> GetData(DataTypeEnum eDataType)
        {
            switch (eDataType)
            {
                case DataTypeEnum.Open:
                    return _lstOpen;
                case DataTypeEnum.High:
                    return _lstHigh;
                case DataTypeEnum.Low:
                    return _lstLow;
                case DataTypeEnum.Close:
                    return _lstClose;
                case DataTypeEnum.Volume:
                    return _lstVolume;
            }
            return null;
        }

    }
}
